import Rect from './Rect.js';
import Polygon from './Polygon.js';
import ArcPolygon from './ArcPolygon.js';
import Circle from './Circle.js';
import Line from './Line.js';
import Quadratic from './Quadratic.js';
import Bezier from './Bezier.js';
import SVG from '../SVG.js';
import Curve from './Curve.js';
import Point from '../Point';

/**
 * 【正则】根据一个指定svg串获取一个（或者第一个）Graph对象
 * @param svgShapes
 * @returns {null|Rect|ArcPolygon|Polygon|Line|Circle|Bezier|Quadratic|*|module:os}
 */
export function getGraphBySvgShapesReg(svgShapes) {
    if (!svgShapes) return null;
    // console.warn('[Graph] getGraphBySvgShapesReg: ', svgShapes);
    const obj = getSimpleObject(svgShapes);
    // console.warn('[Graph] obj: ', obj);
    return getInstanceBySimpleObject(obj);
}

/**
 * get a simple object from a string.
 */
export function getSimpleObject(shapes) {
    let obj = {};
    if (!shapes) return obj;
    const str = shapes.match(/(?<=<).*?(?=>)/g)[0];
    // console.warn('[Graph] str: ', str);
    const arr = str.split(' ');
    if (!arr || !arr.length) return obj;
    // console.warn('[Graph] arr: ', arr);
    let lastName = '';
    for (let i = 0, len = arr.length; i < len; i += 1) {
        let newOne = arr[i].indexOf('=') >= 0;
        if (i === 0) obj.tagName = arr[i];
        // eslint-disable-next-line no-useless-escape
        else if (!newOne && arr[i]) obj[lastName] += ' ' + arr[i].replace(/\"/g, '');
        else if (newOne) {
            const as = arr[i].split('=');
            // eslint-disable-next-line no-useless-escape
            obj[as[0]] = as[1].replace(/\"/g, '');
            lastName = as[0];
        }
    }
    // console.warn('[Graph] obj: ', obj);
    return obj;
}

/**
 * get a simple object from a dom.
 */
export function getSimpleObjectByDom(dom) {
    if (!dom) return null;
    let obj = {
        tagName: dom.tagName,
        x: dom.getAttribute('x'),
        y: dom.getAttribute('y'),
        fill: dom.getAttribute('fill'),
        stroke: dom.getAttribute('stroke'),
        width: dom.getAttribute('width'),
        height: dom.getAttribute('height'),
        rx: dom.getAttribute('rx'),
        points: dom.getAttribute('points'),
        d: dom.getAttribute('d'),
        cx: dom.getAttribute('cx'),
        cy: dom.getAttribute('cy'),
        r: dom.getAttribute('r'),
        'stroke-width': dom.getAttribute('stroke-width')
    };
    return obj;
}

/**
 * 根据一个指定svg串获取一个（或者第一个）Graph对象
 * @author guxulei
 * @date 2021.1.5
 * @param svgShapes
 * @returns {null|Rect|ArcPolygon|Polygon|Line|Circle|Bezier|Quadratic|*|module:os}
 */
export function getGraphBySvgShapes(svgShapes) {
    if (!svgShapes) return null;
    let shapes = SVG.createGroupFromString(svgShapes);
    if (!shapes || !shapes.childNodes || !shapes.childNodes.length) return null;
    return this.getInstanceBySvg(null, null, shapes.childNodes[0]);
}

/**
 * just a unfinished class, convers svg dom to a public Graph class.
 */
export function getInstanceBySvg(ctx, scaling, dom) {
    if (!dom || !dom.tagName) return null;
    const obj = getSimpleObjectByDom(dom);
    if (!obj) return null;
    return getInstanceBySimpleObject(obj, ctx, scaling);
}

export function getInstanceBySimpleObject(obj, ctx, scaling) {
    // console.warn('[Graph] getInstanceBySimpleObject: ', obj, ctx, scaling);
    if (!obj || !obj.tagName) return null;
    let tagName = obj.tagName.toLowerCase(),
        x = parseInt(obj.x),
        y = parseInt(obj.y),
        lineWidth = obj['stroke-width'],
        fillStyle = obj.fill,
        strokeStyle = obj.stroke,
        points = [];
    if (tagName === 'rect') {
        let w = parseInt(obj.width),
            h = parseInt(obj.height),
            radius = parseInt(obj.rx);
        // console.warn('[Graph] getInstanceBySimpleObject: ', obj, lineWidth, ctx, scaling);
        // points = [
        //     { x: x, y: y },
        //     { x: x + w, y: y },
        //     { x: x + w, y: y + h },
        //     { x: x, y: y + h }
        // ]; //eslint-disable-line
        points = [
            { x: x, y: y + h },
            { x: x + w, y: y + h },
            { x: x + w, y: y },
            { x: x, y: y }
        ]; //eslint-disable-line
        return new Rect({ ctx, pos: { x, y }, scaling, points, lineWidth, fillStyle, radius, strokeStyle });
    } else if (tagName === 'polygon') {
        if (!obj.points) return false;

        // 兼容老数据转换，直接只用points生成Polygon
        if (Array.isArray(obj.points)) points = obj.points;
        // 新数据使用svgShapes中的points字符串（同其他d字段）来转换points
        else points = getPointsBySvgPoints(obj.points);
        // points.push(points[0]);
        if (!Point.equals(points[0], points[points.length - 1])) points.push(points[0]);
        return new Polygon({ ctx, pos: points[0], scaling, points, lineWidth, fillStyle, strokeStyle });
    } else if (tagName === 'path') {
        // 兼容老数据转换，直接只用points生成对应Graph对象
        if (obj.points && obj.points.length) {
            const param = { ctx, pos: obj.points[0], scaling, points: obj.points, lineWidth, fillStyle, strokeStyle };
            if (obj.points.length === 2) return new Line(param);
            if (obj.points.length === 3) return new Quadratic(param);
            if (obj.points.length === 4) return new Bezier(param);
            if (obj.points.length > 4) return new Curve(param);
        }

        // 新数据使用svgShapes中的d来转换points
        let d = obj.d,
            isClose = d[d.length - 1] === 'Z',
            isLine = d.indexOf('L'),
            isQuadratic = d.indexOf('Q'),
            isBezier = d.indexOf('C');
        // console.log(isLine > 0 ? 'Graph.getInstanceBySvg: this path is Line' : '');
        // console.log(isQuadratic > 0 && !isClose ? 'Graph.getInstanceBySvg: this path is Quadratic' : '');
        // console.log(isBezier > 0 ? 'Graph.getInstanceBySvg: this path is Bezier' : '');
        // console.log(isQuadratic > 0 && isClose ? 'Graph.getInstanceBySvg: this path is ArcPolygon' : '');
        if (isQuadratic) points = getPointsBySvgPathD(d);
        else points = getPointsBySvgPathD(d);
        let isCurve = points && points.length > 4;
        // console.warn('[Graph] ', obj, points, isCurve);
        if (isClose && !isQuadratic) points.push(points[0]);
        // console.warn('[Graph] constructor: path => ', dom, d, isClose, points);
        const param = { ctx, pos: points[0], scaling, points, lineWidth, fillStyle, strokeStyle };
        if (isCurve && !isClose) return new Curve(param);
        if (isLine > 0) return new Line(param);
        // if (isQuadratic > 0 && !isClose) return new Quadratic(param);
        // if (isBezier > 0) return new Bezier(param);
        if ((isQuadratic > 0 && !isClose) || (isBezier > 0 && points.length === 3)) return new Quadratic(param);
        if (isBezier > 0 && points.length === 4) return new Bezier(param);
        else {
            let o = new ArcPolygon(param);
            o.setComplete(true);
            return o;
        }
    } else if (tagName === 'circle') {
        let x = parseInt(obj.cx),
            y = parseInt(obj.cy),
            radius = parseInt(obj.r),
            points = [{ x: x + radius, y: y }];
        return new Circle({ ctx, pos: { x, y }, scaling, points, lineWidth, fillStyle, strokeStyle, radius });
    }
}

export function getPointsBySvgPoints(d) {
    if (!d) return [];
    let arr = d.match(/-?\d+/g),
        rtn = [];
    for (let i = 0, len = arr.length; i < len; i++) {
        let p = {};
        p.x = parseInt(arr[i++]);
        p.y = parseInt(arr[i]);
        rtn.push(p);
    }
    return rtn;
}

export function getPointsBySvgPathD(d) {
    let rtn = [];
    if (!d) return rtn;
    // only points, no quadratic...
    let arr = d.match(/-?\d*\.?\d+/g);
    for (let i = 0, len = arr.length; i < len; i++) {
        let p = {};
        p.x = parseInt(arr[i++]);
        p.y = parseInt(arr[i]);
        rtn.push(p);
    }
    return rtn;
}

export function getPointsBySvgPathDQ(d) {
    let rtn = [];
    if (!d) return rtn;
    // with quadratic...
    // let arr = d.match(/\S*\s*-?\d*,-?\d*|\S/g);
    // arr.forEach((l, i) => {
    // });
    return rtn;
}
